
public class RelOp implements Expressao {

	private Expressao expr1;
	private Expressao expr2;
	private String op;
	private Tipo tipo;
	private Integer regFinal;
	
	public RelOp(Expressao expr1, Expressao expr2, String op) {
		this.expr1 = expr1;
		this.expr2 = expr2;
		this.op = decodifica(op);
	}
	
	private String decodifica(String op) {
		
		if (op.equals("==") || op.equals("!=")) {
			this.tipo = Tipo.IGUALDADE;
			return op;
		}
		
		this.tipo = Tipo.RELACIONAL;
		if (op.equals(">=")) return "JGE";
		if (op.equals(">")) return "JG";
		if (op.equals("<=")) return "JLE";
		if (op.equals("<")) return "JL";
		
		return "";
	}

	@Override
	public String getCode() {
		StringBuffer sb = new StringBuffer();
		
		Integer reg1 = null;
		Integer reg2 = null;
		String label = ParserUtils.novoLabel();
		String labelFinal = ParserUtils.novoLabel();
		
		String s1 = expr1.getCode();
		if (expr1.possuiRegistradorFinal()) {
			reg1 = expr1.registradorFinal();
			sb.append(s1);
		} else {
			reg1 = ParserUtils.novoRegistrador();
			sb.append("LD R" + reg1 + ", " + s1);
		}
		sb.append(System.lineSeparator());
		
		String s2 = expr2.getCode();
		if (expr2.possuiRegistradorFinal()) {
			reg2 = expr2.registradorFinal();
			sb.append(s2);
		} else {
			reg2 = ParserUtils.novoRegistrador();
			sb.append("LD R" + reg2 + ", " + s2);
		}
		sb.append(System.lineSeparator());
		
		if (tipo == Tipo.IGUALDADE) {
			sb.append("SUB R" + reg1 + ", R" + reg1 + ", R" + reg2);
			sb.append(System.lineSeparator());
			sb.append("JNZ " + label + ", R" + reg1);
			sb.append(System.lineSeparator());
			
			if (op.equals("==")) {
				sb.append("ST R" + reg1 + ", #1");
				sb.append(System.lineSeparator());
				sb.append("JMP " + labelFinal);
				sb.append(System.lineSeparator());
				sb.append(label + ": ST R" + reg1 + ", #0");
			} else {
				sb.append("ST R" + reg1 + ", #0");
				sb.append(System.lineSeparator());
				sb.append("JMP " + labelFinal);
				sb.append(System.lineSeparator());
				sb.append(label + ": ST R" + reg1 + ", #1");
			}
			sb.append(System.lineSeparator());
			ParserUtils.liberaRegistradores(reg2);
		} else {
			sb.append(op + " " + label + ", R" + reg1 + ", R" + reg2);
			sb.append(System.lineSeparator());
			sb.append("ST R" + reg1 + ", #0");
			sb.append(System.lineSeparator());
			sb.append("JMP " + labelFinal);
			sb.append(System.lineSeparator());
			sb.append(label + ": ST R" + reg1 + ", #1");
			sb.append(System.lineSeparator());
		}
		
		regFinal = reg1;
		sb.append(labelFinal + ": ");
		return sb.toString();
	}

	@Override
	public Integer registradorFinal() {
		return regFinal;
	}

	@Override
	public boolean possuiRegistradorFinal() {
		return true;
	}

	private enum Tipo {
		IGUALDADE, RELACIONAL;
	}
	
}
